/**
 * 
 */
package ec.app.deferEvalCoevolve1;

import java.util.Arrays;

import ec.util.MersenneTwister;

/**
 * @author RothmD01
 *
 */
public class BasicRandom {

	MersenneTwister rand;
	CoevoRosenVar2 rosen = new CoevoRosenVar2();
	
	final int nInd = 1600;
	final int mTot = 45000;
	
	public void performBase( long seed ) {
		double tmTrack[][] = new double[2][nInd];
		double outTm[][] = new double[2][mTot];
		double outComes[] = new double[mTot];
		int seqLen = nInd * nInd;
		
		rand = new MersenneTwister();
		rand.setSeed(seed);
		
		for( int i = 0; i < nInd; i++ ) {
			tmTrack[0][i] = rand.nextDouble();
			tmTrack[1][i] = rand.nextDouble();
		}
		
    	// all possible selections
    	int randInd[] = new int[ seqLen ];
    	for( int i = 0; i < seqLen; i++ ) randInd[i] = 0;
    	// the actually selected indexes
    	int selInd[] = new int[ mTot ];
    	for( int i = 0; i < mTot; i++ ) selInd[i] = rand.nextInt(seqLen);
    	// sort 'em to make it easier
    	Arrays.sort( selInd );
    	// use a hash-style next-available to remove the duplicates
    	for( int i = 0; i < mTot; i++ ) {
    		int locInd;
    		locInd = selInd[i];
    		if( randInd[locInd] == 0 ) {
        		// hole is empty
    			randInd[locInd] = 1;
    		} else {
    			// find previous available hole
    			while(randInd[locInd]>0) {
    				locInd -= 1;
    				if( locInd < 0 ) locInd += seqLen;
    			}
    			randInd[locInd] += 1;
    		}
    		selInd[i] = locInd;
    	}
    	
    	// now translate the indexes into actual individual selections, populating the returned teams
    	// for each of the team selections
    	for( int i = 0; i < mTot; i++ ) {
    		int baseInd;
    		baseInd = selInd[i];
    		// for each of the subpopulations
    		for( int j = 0; j < 2; j++ ) {
    			final int sublen = nInd;
    			int locInd;

    			locInd = baseInd % sublen;
    			outTm[j][i] = tmTrack[j][locInd];
    			baseInd /= sublen;
    		}
    		outComes[i] = rosen.rosenbrock(outTm[0][i], outTm[1][i]);
//    		System.out.println( "Ind: "+i+"\tA: "+outTm[0][i]+"\tB: "+outTm[1][i]+"\tOut: "+outComes[i]);
    	}		
    	Arrays.sort(outComes);
    	int nToAvg = 10;
    	double avgN = 0.0;
    	for(int i = 0; i < nToAvg; i++ ) {
    		avgN += outComes[mTot - 1 - i ];
    	}
    	avgN /= (double)nToAvg;
    	System.out.println( "Best: "+outComes[mTot-1]+"\tAvgOf "+nToAvg+": "+avgN);
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		BasicRandom base;

		final long seedArr[] = {
				253,
				754,
				9,
				9019,
				2,
				6,
				106,
				526,
				3,
				37,
				8520,
				1,
				345,
				868,
				9594,
				5,
				12,
				43,
				9,
				4,
				1499,
				33,
				4104,
				469,
				9329
		};
		final int iter = seedArr.length;		
		
		for( int i = 0; i < iter; i++ ) {
			base = new BasicRandom();
			base.performBase(seedArr[i]);
		}

	}

}
